﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Diagnostics;
using Twc.Deployment.Client.Logic.Commands;
using System.Threading;

namespace Twc.Deployment.Client.Logic.DeploymentActions
{
    public class WSPDeployAction : BaseDeployAction
    {

        public WSPDeployAction(DeployService deployService)
            : base(deployService)
        {

        }

        public override DeploymentResult Deploy()
        {
            var wspDirectory = getWSPFolder();
            var deploymentResult = new DeploymentResult();


            foreach (var packageDirectory in wspDirectory.GetDirectories())
            {
                //If there is setup.bat file i will call it directly
                if (packageDirectory.GetFiles("setup.bat", SearchOption.TopDirectoryOnly).FirstOrDefault() != null)
                {
                    using (var processService = new ProcessService())
                    {
                        CommandGenerator = getSetupCommand();
                        (CommandGenerator as WSPSetupCommandGenerator).InstallationType = InstallationType.INSTALL;

                        processService.WriteCommand(packageDirectory.Root.Name.Replace(@"\", ""));

                        processService.WriteCommand("cd " + packageDirectory.FullName);
                        //processService.WriteCommandAndWait(CommandGenerator.GenerateCommand(), 6000);
                        processService.WriteCommand(CommandGenerator.GenerateCommand());
                        processService.WriteCommand("");

                        deploymentResult.CommandInput += CommandGenerator.GenerateCommand() + Environment.NewLine;
                        deploymentResult.CommandOutput += processService.ReadOutput() + Environment.NewLine;
                    }

                }
                //otherwise i need to call STSADM commands to add and deploy the solution
                else
                {
                    var solutionFile = packageDirectory.GetFiles("*.wsp").FirstOrDefault();

                    using (var processService = new ProcessService())
                    {
                        CommandGenerator = new STSADMCommandGenerator();
                        (CommandGenerator as STSADMCommandGenerator).Operation = Operation.SOLUTION_ADD;
                        (CommandGenerator as STSADMCommandGenerator).FileName = solutionFile.FullName;

                        processService.WriteCommand("c:");

                        processService.WriteCommand("cd " + SP12HIVE + @"\BIN");
                        processService.WriteCommandAndWait(CommandGenerator.GenerateCommand(), 6000);
                        processService.WriteCommand("");

                        deploymentResult.CommandInput += CommandGenerator.GenerateCommand() + Environment.NewLine;
                        deploymentResult.CommandOutput += processService.ReadOutput() + Environment.NewLine;
                    }
                    using (var processService = new ProcessService())
                    {
                        (CommandGenerator as STSADMCommandGenerator).Operation = Operation.SOLUTION_DEPLOY;
                        (CommandGenerator as STSADMCommandGenerator).FileName = solutionFile.Name;
                        (CommandGenerator as STSADMCommandGenerator).Url = this.DeployService.SiteCollection.Url;
                        (CommandGenerator as STSADMCommandGenerator).Immediate = true;
                        (CommandGenerator as STSADMCommandGenerator).AllowGacDeployment = true;
                        (CommandGenerator as STSADMCommandGenerator).Force = true;

                        processService.WriteCommand("cd " + SP12HIVE + @"\BIN");
                        processService.WriteCommandAndWait(CommandGenerator.GenerateCommand(), 6000);
                        processService.WriteCommand("");

                        deploymentResult.CommandInput += CommandGenerator.GenerateCommand() + Environment.NewLine;
                        deploymentResult.CommandOutput += processService.ReadOutput() + Environment.NewLine;
                    }
                }



            }
            return deploymentResult;
        }

        private DirectoryInfo getWSPFolder()
        {
            return new FileInfo(this.GetType().Assembly.Location).Directory.GetDirectories("WSP").FirstOrDefault();
        }

        public override DeploymentResult Undeploy()
        {
            var wspDirectory = getWSPFolder();
            var deploymentResult = new DeploymentResult();


            foreach (var packageDirectory in wspDirectory.GetDirectories())
            {
                //If there is setup.bat file i will call it directly
                if (packageDirectory.GetFiles("setup.bat", SearchOption.TopDirectoryOnly).FirstOrDefault() != null)
                {
                    using (var processService = new ProcessService())
                    {
                        CommandGenerator = getSetupCommand();
                        (CommandGenerator as WSPSetupCommandGenerator).InstallationType = InstallationType.UNINSTALL;

                        processService.WriteCommand(packageDirectory.Root.Name.Replace(@"\", ""));

                        processService.WriteCommand("cd " + packageDirectory.FullName);
                        //processService.WriteCommandAndWait(CommandGenerator.GenerateCommand(), 6000);
                        processService.WriteCommand(CommandGenerator.GenerateCommand());
                        processService.WriteCommand("");

                        deploymentResult.CommandInput += CommandGenerator.GenerateCommand() + Environment.NewLine;
                        deploymentResult.CommandOutput += processService.ReadOutput() + Environment.NewLine;
                    }
                }
                //otherwise i need to call STSADM commands to remove and retract the solution
                else
                {
                    var solutionFile = packageDirectory.GetFiles("*.wsp").FirstOrDefault();
                    using (var processService = new ProcessService())
                    {
                        CommandGenerator = new STSADMCommandGenerator();

                        (CommandGenerator as STSADMCommandGenerator).Operation = Operation.SOLUTION_RETRACT;
                        (CommandGenerator as STSADMCommandGenerator).FileName = solutionFile.Name;
                        (CommandGenerator as STSADMCommandGenerator).Url = this.DeployService.SiteCollection.Url;
                        (CommandGenerator as STSADMCommandGenerator).Immediate = true;

                        processService.WriteCommand("c:");

                        processService.WriteCommand("cd " + SP12HIVE + @"\BIN");
                        processService.WriteCommand(CommandGenerator.GenerateCommand());

                        deploymentResult.CommandInput += CommandGenerator.GenerateCommand() + Environment.NewLine;
                        deploymentResult.CommandOutput += processService.ReadOutput() + Environment.NewLine;
                    }

                    using (var processService = new ProcessService())
                    {
                        (CommandGenerator as STSADMCommandGenerator).Operation = Operation.SOLUTION_DELETE;
                        (CommandGenerator as STSADMCommandGenerator).FileName = solutionFile.Name;
                        (CommandGenerator as STSADMCommandGenerator).Override = true;

                        processService.WriteCommand("cd " + SP12HIVE + @"\BIN");
                        processService.WriteCommandAndWait(CommandGenerator.GenerateCommand(), 6000);
                        processService.WriteCommand("");

                        deploymentResult.CommandInput += CommandGenerator.GenerateCommand() + Environment.NewLine;
                        deploymentResult.CommandOutput += processService.ReadOutput() + Environment.NewLine;
                    }
                }
                

            }
            return deploymentResult;
        }

        private WSPSetupCommandGenerator getSetupCommand()
        {
            var setupCommand = new WSPSetupCommandGenerator();
            setupCommand.SiteCollectionUrl = this.DeployService.SiteCollection.Url;
            setupCommand.SubsiteUrl = this.DeployService.SiteCollection.Url;

            return setupCommand;
        }
    }
}
